package com.sinaapp.gavinzhang.ConcurrentProgramming;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by gavin on 15-9-1.
 */
public class MultipleConditionProducerConsumer {
    public static void main(String[] args)
    {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,2,5000L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
        StringStorage stringStorage = new StringStorage();
        threadPoolExecutor.execute(new LockConsumer(stringStorage));
        threadPoolExecutor.execute(new LockProducer(stringStorage));
    }
}

class LockConsumer implements Runnable{
    private StringStorage eventStorage;

    public LockConsumer(StringStorage eventStorage) {
        this.eventStorage = eventStorage;
    }

    public void run() {
        while (true)
        {
            try {
                Thread.sleep(600);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(eventStorage.get());

        }

    }
}

class LockProducer implements Runnable{
    private StringStorage eventStorage;

    public LockProducer(StringStorage eventStorage) {
        this.eventStorage = eventStorage;
    }

    public void run() {
        while (true)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            eventStorage.add(Thread.currentThread().getName()+" "+ System.currentTimeMillis());
        }

    }
}


class StringStorage implements Serializable{
    private Lock lock;
    private Condition notFull;
    private Condition notEmpty;
    private int max=5;
    private List<String> list = new ArrayList<String>();

    public StringStorage() {
        lock = new ReentrantLock();
        notFull = lock.newCondition();
        notEmpty = lock.newCondition();
    }

    public void add(String str)
    {
        lock.lock();
        try {
            while (list.size() == max)
            {
                try {
                    notFull.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.add(str);
            System.out.println("add one message");
            notEmpty.signalAll();
        }finally {
            lock.unlock();
        }

    }

    public String get()
    {
        lock.lock();
        try {
            while (list.size() == 0)
            {
                try {
                    notEmpty.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            String str = list.remove(0);
            notFull.signalAll();
            return str;
        }finally {
            lock.unlock();
        }
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}